const { v4: uuidv4 } = require('uuid')
const {
  generateCompanyName,
  generateUniqueCode,
  getRandomElement,
  generateRandomInteger,
  generateTrainingParams,
  generateRandomLowerCaseString,
  generateRandomIntegerLenght,
  generateSerialNumbers,
  randomUpperCase,
  getRandomRisk,
  getRandomItems,
  getDateRange,
  getRandomDateBetween
} = require('../common/common')
const log4js = require('../utils/log4')
const logger = log4js.getLogger('server/hooks/index.js')
const prisma = require('../utils/prisma')
const { Decimal } = require('@prisma/client/runtime/library')
const { displayUrlPrefix } = require('../config/index')

module.exports = {
  /** 模拟用户数据 */
  async addCustom(num, startDate, endDate) {
    const GetLastUser = await prisma.custom.findFirst({
      where: {},
      select: {
        custom_name: true
      },
      orderBy: {
        custom_name: "desc"
      }
    })
    // console.log(GetLastUser)
    let match, satrtNum
    try {
      const regex = /\d+/; // \d+ 匹配一个或多个数字
      GetLastUser ? satrtNum = parseInt(GetLastUser.custom_name.match(regex)) : satrtNum = 0
      // match = parseInt(satrtNum.match(regex)) ? parseInt(satrtNum.match(regex)) : 0;
      // console.log(parseInt(GetLastUser.custom_name.match(regex)))
    } catch (error) {
      logger.debug('不是数字')
    }
    // console.log(num,satrtNum)
    const NeedAddCusto = generateSerialNumbers('HY_s', satrtNum + 1, (satrtNum + num))
    const customList = []
    // logger.info(NeedAddCusto)
    // console.log(getDateRange(startDate).startOfDay,getDateRange(endDate).endOfDay)
    for (let i = 0; i < NeedAddCusto.length; i++) {
      const oneCustom = {
        custom_name: NeedAddCusto[i],
        access_key: randomUpperCase(uuidv4()),
        secret_key: uuidv4(),
        enable: true,
        remarks: '',
        is_del: false,
        display_time: this.randomDate(startDate, endDate),
        custom_admin_id: 27
      }
      customList.push(oneCustom)
    }

    // db操作
    prisma.custom
      .createMany({
        data: customList
      })
      .then(res => {
        logger.info(`模拟用户数据-成功结果:生成 ${res.count} 条数据`)
        logger.info(`模拟数据:${JSON.stringify(customList, null, 2)}`)
      })
      .catch(err => {
        logger.error(`模拟用户数据-失败结果: ${err}`)
      })
  },

  /** 模拟素材数据 */
  async addMaterial(num, minSize, maxSize, startDate, endDate) {
    const customIds = await prisma.custom
      .findMany({
        select: {
          id: true
        }
      })
      .then(res => res.map(item => item.id))
    if (customIds <= 0) {
      logger.error('模拟素材数据-失败结果: 没有模拟用户数据，请先模拟用户数据')
      return
    }
    const materialList = []
    const customModelRelations = []
    const ModelNum = await prisma.ai_models.count({})
    for (let i = 0; i < num; i++) {
      const custom_id = getRandomElement(customIds)
      const file_type = generateRandomInteger(1, ModelNum)
      const C_file_type = generateRandomInteger(31, 45)
      console.log(file_type)
      const oneMaterial = {
        id: generateUniqueCode(),
        url: '',
        custom_id,
        file_size: generateRandomInteger(minSize * 1024 * 1024, maxSize * 1024 * 1024),
        usage_count: generateRandomInteger(1, 2),
        file_type: C_file_type,
        real_link: false,
        is_del: false,
        create_time: this.randomDate(startDate, endDate)
      }
      const ModelMap = await this.GetModel()

      const oneRelation = {
        model_id: ModelMap[file_type + ''],
        custom_id
      }
      materialList.push(oneMaterial)
      customModelRelations.push(oneRelation)
    }
    console.log(materialList)
    // db操作
    prisma.material
      .createMany({
        data: materialList
      })
      .then(res => {
        logger.info(`模拟素材数据-成功结果:生成 ${res.count} 条数据`)
        logger.info(`模拟数据:${JSON.stringify(materialList, null, 2)}`)
      })
      .catch(err => {
        logger.error(`模拟素材数据-失败结果: ${err}`)
      })

    // 构建 OR 条件数组
    const orConditions = customModelRelations.map(({ model_id, custom_id }) => ({
      AND: [{ model_id }, { custom_id }]
    }))

    // 使用 findMany 查询已存在的数据
    const existingData = await prisma.custom_model_relations.findMany({
      where: {
        OR: orConditions
      }
    })

    // 将已存在的数据的 model_id 和 custom_id 构建成 Set
    const existingIds = new Set(existingData.map(({ model_id, custom_id }) => `${model_id}_${custom_id}`))

    // 过滤出需要插入的数据
    const newData = customModelRelations.filter(({ model_id, custom_id }) => !existingIds.has(`${model_id}_${custom_id}`))

    // 插入新数据
    if (newData.length > 0) {
      prisma.custom_model_relations
        .createMany({
          data: newData
        })
        .then(res => {
          logger.info(`模拟用户AI关联数据-成功结果:生成 ${res.count} 条数据`)
          logger.info(`模拟用户AI关联数据:${JSON.stringify(newData, null, 2)}`)
        })
        .catch(err => {
          logger.error(`模拟用户AI关联数据-失败结果: ${err}`)
        })
    }
  },

  /** 模拟训练数据 */
  async addTrain(num, flag, training_results, startDate, endDate) {
    const material = await prisma.material.findMany({
      take: 500,
      select: {
        id: true,
        custom_id: true,
        file_size: true,
        file_type: true
      },
      where: {
        is_del: false
      }
    })
    console.log(material)
    if (material.length == 0) return

    // 获取AI列表
    const aiList = await prisma.ai_models
      .findMany({
        select: {
          id: true
        }
      })
      .then(res => res.map(item => item.id))

    if (aiList == 0) return
    console.log(aiList)
    // 遍历素材添加训练记录
    const reportsRecord = []
    for (let i = 0; i < num; i++) {
      // 获取随机一个素材
      const randomMaterial = getRandomElement(material)
      const training_time = generateRandomInteger(30, 120)
      const randomInteger = generateRandomInteger(90, 110)
      const oneMaterial = {
        material_id: randomMaterial.id,
        ai_id: aiList[generateRandomInteger(0, aiList.length)], // 对应下标取
        training_time,
        size: parseInt((((training_time * 60) / 30) * 124.4 * randomInteger) / 100),
        training_results: flag ? training_results : getRandomElement(['done', 'doing', 'wait']),
        args: JSON.stringify(generateTrainingParams(randomMaterial.file_type)),
        hit_rate: new Decimal(generateRandomInteger(92, 98)),
        delay: generateRandomInteger(5, 20),
        create_time: this.randomDate(startDate, endDate)
      }
      reportsRecord.push(oneMaterial)
    }
    console.log(reportsRecord)
    // 添加模型训练
    prisma.training_report
      .createMany({
        data: reportsRecord
      })
      .then(res => {
        logger.info(`模拟模型训练数据-成功结果:生成 ${res.count} 条数据`)
        logger.info(`模拟模型训练数据:${JSON.stringify(reportsRecord, null, 2)}`)
      })
      .catch(err => {
        logger.error(`模拟模型训练数据-失败结果: ${err}`)
      })
  },

  /** 随机生成一个给定时间范围内的Date结果 */
  randomDate(startDate, endDate) {
    // 将开始时间和结束时间转换为时间戳
    const startTimestamp = new Date(startDate).getTime()
    const endTimestamp = new Date(endDate).getTime() + (86400000 - 1)

    // 在时间范围内生成随机的时间戳
    const randomTimestamp = startTimestamp + Math.random() * (endTimestamp - startTimestamp)

    // 将随机的时间戳转换为日期对象
    return new Date(randomTimestamp)
  },
  async GetModel() {
    const ModelRes = await prisma.ai_models.findMany()
    let ModelMap = {}
    ModelRes.map((item, index) => {
      ModelMap[index + 1] = item.id
    })
    // console.log(ModelMap)
    return ModelMap
  },
  modelMap: {
    1: 7,
    2: 8,
    3: 9,
    4: 10,
    5: 11,
    6: 12,
    7: 13,
    8: 14,
    9: 15,
    10: 16,
    11: 17,
    12: 18
  },
  async addNewMaterial(num, startDate, endDate) {
    if ((!num) || (!startDate) || (!endDate)) { throw new Error('缺少参数') }
    try {
      for (let index = 0; index < Number(num); index++) {
        const createRes = await prisma.govern.createMany({
          data: {
            url: displayUrlPrefix + uuidv4() + '.zip',
            display_id: randomUpperCase(uuidv4()),
            admin_id: 27,
            display_time: this.randomDate(startDate, endDate),
            material_size: generateRandomInteger(300, 1800)
          }
        })
      }
    } catch (error) {
      logger.error(error)
    }
  },
  // addMonitor
  async addMonitor(num, startDate, endDate) {
    if ((!num) || (!startDate) || (!endDate)) { throw new Error('缺少参数') }
    try {
      for (let index = 0; index < Number(num); index++) {
        const createRes = await prisma.monitor.createMany({
          data: {
            url: displayUrlPrefix + uuidv4() + '.zip',
            display_id: randomUpperCase(uuidv4()),
            admin_id: 27,
            display_time: this.randomDate(startDate, endDate),
            material_size: generateRandomInteger(300, 1800)
          }
        })
      }
    } catch (error) {
      logger.error(error)
    }
  },
  async addReportGovern(num, startDate, endDate) {
    for (let index = 0; index < Number(num); index++) {
      const lastMeterialId = await prisma.govern.findFirst({
        where: {
          is_del: 0
        },
        select: {
          id: true
        },
        orderBy: {
          id: 'desc'
        }
      })
      let RandomMaterial, RandomId
      for (let index = 0; index < 3; index++) {
        // console.log(index)
        RandomId = generateRandomInteger(1, lastMeterialId.id)
        RandomMaterial = await prisma.govern.findFirst({
          where: {
            is_del: 0,
            id: RandomId
          },
          select: {
            id: true
          }
        })
        // console.log(RandomId)
        if (RandomMaterial) {
          break
        }
        // if (index == 2) {
        //   RandomMaterial = lastMeterialId
        // }
      }
      if(!RandomMaterial){
        RandomMaterial = lastMeterialId
      }
      // console.log('素材最终结果',RandomMaterial)
      const lastCustomId = await prisma.custom.findFirst({
        where: {
          is_del: false
        },
        select: {
          id: true
        },
        orderBy: {
          id: 'desc'
        }
      })
      let RandomCustom, RandomCustomId
      // console.log(lastCustomId.id)
      for (let j = 0; j < 3; j++) {
        RandomCustomId = generateRandomInteger(1, lastCustomId.id)
        RandomCustom = await prisma.custom.findFirst({
          where: {
            is_del: false,
            id: RandomCustomId
          },
          select: {
            id: true
          }
        })
        if (RandomCustom) {
          // console.log('幼稚跳出',RandomCustom)
          break
        }
      }
      if(!RandomCustom){
        RandomCustom = lastCustomId
      }
      // console.log('最终结果',RandomCustom)
      let type = ['safety_analysis', 'clear_err', 'format_conversion', 'missing_value', 'duplicate_value', 'arrange']
      let gover_type = new Object()
      const choosedType = getRandomItems(type, 3, 5)
      // console.log(choosedType)
      for (let index = 0; index < type.length; index++) {
        if (choosedType.indexOf(type[index]) != -1) {
          switch (type[index]) {
            case 'safety_analysis':
              gover_type['safety_analysis'] = Number(getRandomRisk({
                1: 0.70,
                2: 0.25,
                3: 0.05
              }))
              break;
            case 'clear_err':
              gover_type['clear_err'] = Number(getRandomRisk({
                1: 0.50,
                2: 0.40,
                3: 0.10
              }))
              break;
            case 'format_conversion':
              gover_type['format_conversion'] = 1
              break;
            case 'missing_value':
              gover_type['missing_value'] = Number(getRandomRisk({
                1: 0.50,
                2: 0.40,
                3: 0.10
              }))
              break;
            case 'duplicate_value':
              gover_type['duplicate_value'] = Number(getRandomRisk({
                1: 0.50,
                2: 0.40,
                3: 0.10
              }))
              break;
            case 'arrange':
              gover_type['arrange'] = 1
              break;
            default:
              break;
          }
        }else{
          gover_type[type[index]] = null
        }
      }
      // console.log(gover_type)
      const inSet = await prisma.report_govern.createMany({
        data: {
          govern_id: RandomMaterial.id,
          size: generateRandomInteger(500, 3000),
          end_time: this.randomDate(startDate, endDate),
          retention: generateRandomInteger(40, 70),
          govern_num: Number(getRandomRisk({
            1: 0.95,
            2: 0.04,
            3: 0.01
          })),
          // gover_type: JSON.stringify(getRandomItems([1, 2, 3, 4, 5], 3, 5)),
          sdk_id:RandomCustom.id,
          ...gover_type
        }
      })
    }
  },
  async addReportMonitor(num, startDate, endDate) {
    const lastMeterialId = await prisma.govern.findFirst({
      where: {
        is_del: 0
      },
      select: {
        id: true
      },
      orderBy: {
        id: 'desc'
      }
    })
    let RandomMaterial, RandomId
    for (let index = 0; index < 3; index++) {
      // console.log('index',index)
      RandomId = generateRandomInteger(1, lastMeterialId.id)
      RandomMaterial = await prisma.govern.findFirst({
        where: {
          is_del: 0,
          id: RandomId
        },
        select: {
          id: true
        }
      })
      // console.log(RandomMaterial)
      // console.log('RandomId',RandomId)
      if (RandomMaterial) {
        break
      }
      if (index == 1) {
        RandomMaterial = lastMeterialId
      }
    }
    logger.info('RandomMaterial.id', RandomMaterial.id)

    for (let index = 0; index < Number(num); index++) {
      let sensitive_words_Random = Number(getRandomRisk({
        0: 0.95,
        1: 0.004,
        2: 0.004,
        3: 0.004,
        4: 0.004,
        5: 0.004,
        6: 0.004,
        7: 0.004,
        8: 0.004,
        9: 0.004,
        10: 0.004,
        11: 0.01
      }))
      let negative_content_Random = Number(getRandomRisk({
        0: 0.95,
        1: 0.004,
        2: 0.004,
        3: 0.004,
        4: 0.004,
        5: 0.004,
        6: 0.004,
        7: 0.004,
        8: 0.004,
        9: 0.004,
        10: 0.004,
        11: 0.01
      }))
      let violations_Random = Number(getRandomRisk({
        0: 0.95,
        1: 0.004,
        2: 0.004,
        3: 0.004,
        4: 0.004,
        5: 0.004,
        6: 0.004,
        7: 0.004,
        8: 0.004,
        9: 0.004,
        10: 0.004,
        11: 0.01
      }))
      try {
        await prisma.report_monitor.createMany({
          data: {
            monitor_id: RandomMaterial.id,
            time_consuming: generateRandomInteger(120, 1800),
            end_time: this.randomDate(startDate, endDate),
            sensitive_words: sensitive_words_Random,
            negative_content: negative_content_Random,
            violations: violations_Random,
            report_status: (sensitive_words_Random + negative_content_Random + violations_Random) > 0 ? 0 : 1,
            sdk_name: getRandomElement(generateSerialNumbers('LMC_s', 1, 100))
          }
        })
      } catch (error) {
        logger.error(error)
      }
    }
  },
  async addGames(num, startDate, endDate) {
    for (let index = 0; index < Number(num); index++) {
      const CreateRes = await prisma.report_games.createMany({
        data: {
          display_id: randomUpperCase(uuidv4()),
          monitor_time: generateRandomInteger(550, 7200),
          monitor_date: this.randomDate(startDate, endDate),
          rendering: Number(getRandomRisk({
            1: 0.05,
            2: 0.60,
            3: 0.35
          })),
          network_delay: generateRandomInteger(9, 120),
          monitor_bug: Number(getRandomRisk({
            0: 0.95,
            1: 0.05
          })),
          sdk_name: getRandomElement(generateSerialNumbers('LMC_s', 1, 100))
        }
      })
    }
  }
}
